package com.ygo.feihua.util;

import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author 朱海洋 E-mail:1799426163@qq.com
 * @date 2017年09月02日下午03:17:49
 * @version 1.0
 */
public class WenBase64 {
	private static char[] baseChar = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
			'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
			'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', '+', '/' };
	private static char[] urlBaseChar = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
			'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
			'5', '6', '7', '8', '9', '-', '_' };

	public static String base64Code(String src, String charsetName) throws UnsupportedEncodingException {
		byte[] buf = src.getBytes(charsetName);
		int len = buf.length;
		List<Byte> list = new LinkedList<Byte>();
		base64Code(buf, len, list);
		StringBuilder sb = new StringBuilder();
		for (byte b : list)
			sb.append(baseChar[b]);
		if (len % 3 == 1)
			sb.append("==");
		else if (len % 3 == 2)
			sb.append("=");
		return sb.toString();
	}

	public static String urlBase64Code(String src, String charsetName) throws UnsupportedEncodingException {
		byte[] buf = src.getBytes(charsetName);
		int len = buf.length;
		List<Byte> list = new LinkedList<Byte>();
		base64Code(buf, len, list);
		StringBuilder sb = new StringBuilder();
		for (byte b : list)
			sb.append(urlBaseChar[b]);
		if (len % 3 == 1)
			sb.append("..");
		else if (len % 3 == 2)
			sb.append(".");
		return sb.toString();
	}

	private static void base64Code(byte[] buf, int len, List<Byte> list) {
		byte temp = 0;
		boolean bool = true;
		for (int i = 0; i <= len; i++) {
			if (i == len)
				bool = false;
			switch (i % 3) {
			case 0:
				if (bool) {
					temp = (byte) ((buf[i] & 0xFC) >>> 2);
					list.add(temp);
					temp = (byte) ((buf[i] & 0x03) << 4);
				}
				break;
			case 1:
				if (bool)
					temp += (byte) ((buf[i] & 0xF0) >>> 4);
				list.add(temp);
				if (bool)
					temp = (byte) ((buf[i] & 0x0F) << 2);
				break;
			case 2:
				if (bool)
					temp += (byte) ((buf[i] & 0xC0) >>> 6);
				list.add(temp);
				if (bool) {
					temp = (byte) (buf[i] & 0x3F);
					list.add(temp);
				}
				break;
			}
		}
	}

	public static String base64Decode(String src, String charsetName) throws UnsupportedEncodingException {
		if (src.contains("="))
			src = src.substring(0, src.indexOf("="));
		byte[] buf = new byte[src.length()];
		for (int i = 0; i < src.length(); i++) {
			buf[i] = indexOf(baseChar, src.charAt(i));
		}
		int len = buf.length;
		List<Byte> list = new LinkedList<Byte>();
		base64Decode(buf, len, list);
		byte[] bytes = new byte[list.size()];
		for (int i = 0; i < list.size(); i++)
			bytes[i] = list.get(i);
		return new String(bytes);
	}

	public static String urlBase64Decode(String src, String charsetName) throws UnsupportedEncodingException {
		if (src.contains("."))
			src = src.substring(0, src.indexOf("."));
		byte[] buf = new byte[src.length()];
		for (int i = 0; i < src.length(); i++) {
			buf[i] = indexOf(urlBaseChar, src.charAt(i));
		}
		int len = buf.length;
		List<Byte> list = new LinkedList<Byte>();
		base64Decode(buf, len, list);
		byte[] bytes = new byte[list.size()];
		for (int i = 0; i < list.size(); i++)
			bytes[i] = list.get(i);
		return new String(bytes);
	}

	private static void base64Decode(byte[] buf, int len, List<Byte> list) {
		byte temp = 0;
		boolean bool = true;
		for (int i = 0; i <= len; i++) {
			if (i == len)
				bool = false;
			if (!bool && temp == 0)
				return;
			switch (i % 4) {
			case 0:
				if (bool)
					temp = (byte) ((buf[i] & 0x3F) << 2);
				break;
			case 1:
				if (bool)
					temp += (byte) ((buf[i] & 0x30) >>> 4);
				list.add(temp);
				if (bool)
					temp = (byte) ((buf[i] & 0x0F) << 4);
				break;
			case 2:
				if (bool)
					temp += (byte) ((buf[i] & 0x3C) >>> 2);
				list.add(temp);
				if (bool)
					temp = (byte) ((buf[i] & 0x03) << 6);
				break;
			case 3:
				if (bool)
					temp += (byte) ((buf[i] & 0x3F));
				list.add(temp);
				break;
			}
		}
	}

	private static byte indexOf(char[] chars, char c) {
		for (byte i = 0; i < chars.length; i++)
			if (chars[i] == c)
				return i;
		return -1;
	}
}
